﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "InplaceEditModeBehavior.h"
#include "InplaceEditProjectReference.h"
#include "InplaceEditSharedContent.h"

// 平台头文件
#include "IElementParentReporter.h"
#include "IDocument.h"
#include "IModelLine.h"
#include "IGenericElement.h"
#include "DbObjectUtils.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

const std::wstring InplaceEditModeBehavior::InplaceEditModeType = L"InplaceEditModeType";

DBOBJECT_DATA_DEFINE(InplaceEditModeBehavior)
{
    SetProjectAppPort__(0);
}

//返回值可能为nullptr
IEditMode* InplaceEditModeBehavior::Create(IDocument* pDoc)
{
    return IEditMode::Create(pDoc, NEW_AS_OWNER_PTR(InplaceEditModeBehavior));
}

bool gcmp::InplaceEditModeBehavior::IsInEditMode(gcmp::IDocument* pDoc)
{
    if (!pDoc)
    {
        return false;
    }
    IEditMode *pEditMode = IEditMode::GetTopActiveEditMode(pDoc);
    if (!pEditMode)
    {
        return false;
    }
    if (pEditMode->GetEditModeType() == InplaceEditModeBehavior::InplaceEditModeType)
    {
        return true;
    }
    return false;
}

const InplaceEditModeBehavior *gcmp::InplaceEditModeBehavior::Get(gcmp::IDocument* pDoc)
{
    const IEditMode *pEditMode = IEditMode::Get(pDoc, InplaceEditModeType);
    if (pEditMode)
    {
        return quick_cast<InplaceEditModeBehavior>(pEditMode->GetEditModeBehavior());
    }
    return nullptr;
}

InplaceEditModeBehavior *gcmp::InplaceEditModeBehavior::GetFw(gcmp::IDocument* pDoc)
{
    IEditMode *pEditMode = IEditMode::Get(pDoc, InplaceEditModeType);
    if (pEditMode)
    {
        return quick_cast<InplaceEditModeBehavior>(pEditMode->GetEditModeBehavior());
    }
    return nullptr;
}

bool InplaceEditModeBehavior::StartEditing(IDocument* pDoc, bool isCreating)
{
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDoc, false, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IEditMode* pBlendEditMode = IEditMode::Get(pDoc, GetEditModeType());
    DBG_WARN_AND_RETURN_UNLESS(pBlendEditMode != nullptr, false, L"pSketchEditMode为空",L"GDMPLab",L"2024-03-30");

    return true;
}

bool InplaceEditModeBehavior::EndEditing(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_UNLESS(nullptr != pDoc, false, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IEditMode* pBlendEditMode = IEditMode::Get(pDoc, GetEditModeType());
    DBG_WARN_AND_RETURN_UNLESS(pBlendEditMode != nullptr, false, L"pBlendEditMode为空",L"GDMPLab",L"2024-03-30");

    return true;
}

ElementId gcmp::InplaceEditModeBehavior::GetReferenceElementId(Int64 projectElementId) const
{
    auto iter = GetProjectIdToReferenceElementIds__().find(projectElementId);
    if (iter != GetProjectIdToReferenceElementIds__().end())
    {
        return iter->second;
    }
    return ElementId::InvalidID;
}

void gcmp::InplaceEditModeBehavior::AddReferenceElement(ElementId referenceElementId, Int64 projectElementId)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(GetProjectIdToReferenceElementIds__().find(projectElementId) == GetProjectIdToReferenceElementIds__().end(), L"族环境的项目对象引用已存在",L"GDMPLab",L"2024-03-30");
    GetProjectIdToReferenceElementIdsFW__()[projectElementId] = referenceElementId;
}

bool InplaceEditModeBehavior::IsElementEditable(const IElement* pElement) const
{
    if (!pElement)
    {
        return true;
    }
    const IGenericElement* pGenericElement = quick_cast<IGenericElement>(pElement);
    if (pGenericElement && quick_cast<InplaceEditProjectReference>(pGenericElement->GetExternalObject()))
    {
        return false;
    }

    return true;
}

void InplaceEditModeBehavior::ReportParents(IDocument* pDoc, gcmp::IElementParentReporter &reporter) const
{
    IEditMode* pEditMode = IEditMode::Get(pDoc, GetEditModeType());
    reporter.ReportWeak(pEditMode->GetEditingElementId());
    FOR_EACH(item, GetProjectIdToReferenceElementIds__())
    {
        reporter.ReportWeak(item.second);
    }
}

void InplaceEditModeBehavior::UpdateForWeakParentDeletion(IDocument* pDoc, const std::set<gcmp::ElementId>& deletedElementIds)
{
    IEditMode* pEditMode = IEditMode::Get(pDoc, GetEditModeType());
    if (deletedElementIds.find(pEditMode->GetEditingElementId()) != deletedElementIds.end())
    {
        DBG_WARN(L"不应该在EditMode有效时删除其中引用的Element",L"GDMPLab",L"2024-03-30");
    }
}

